DOS CGI Scripting Background


The demo page and some examples in the documentation require the server to run back-end scripts in a DOS window. They will fail if you don't have enough environment space. Add a line CommandEnvSize=8192 (or whatever you need) to the [NonWindowsApp] section of SYSTEM.INI.

Introduction

Needless to say, Windows has an unusual environment. If you are familiar with Unix systems, this is going to seem baroque to you. On the other hand, you might as well get used to multi-environment systems. Windows NT has a micro-kernel that supports four "environment subsystems" (DOS, POSIX, Windows-32, and OS/2) with a clever kernel-level client-server architecture. Furthermore, Windows-32 supports both console-style and GUI applications, either of which can start applications that run under any of the other environment subsystems. Finally, the upcoming "Chicago" release of Windows will have both DOS and Windows environments, just like the current version.

DOS Virtual Machines

OK, back to the present. The Windows environment has no native command interpreter. However, a Windows application (like httpd) can create a DOS virtual machine (VM) and make use of the services of the DOS command interpreter. On the other hand, a DOS VM cannot start a Windows application. Since the script runs in the DOS VM, the script is limited to running DOS programs. Normally this is not a big deal.


Environment Variables

When a client issues a request to the server, it sends a message that contains information needed to satisfy the request. Normally the server uses this information directly to return the appropriate document in the appropriate format. When the target of the client's request is a script, the server creates a number of environment variables which contain the information needed for the script to satisfy the client's request. These variables, and their contents, are a core part of the CGI/1.0 specification.

Environment variables created by a Windows application are not available to a DOS VM started by that application. Therefore, the httpd server must create a "jacket script" which contains the commands to define the CGI environment variables within the DOS VM's environment before invoking the actual script.


Standard Input and Output

There is no way for a Windows application to connect pipes to a program running in a DOS VM. Windows Sockets socket descriptors cannot be used in place of file descriptors (all this goes away on NT, by the way). CGI/1.0 requires that a script be able to write its results to its standard output, and read any content furnished by the client on its standard input.

In order to create an environment that conforms to the CGI/1.0 specification, the Windows httpd server creates its script command line with redirection to and from temporary files, and manages those files automatically. The effect is to create a CGI/1.0 environment with no special action needed by the script. Content furnished by a client as part of a (e.g., PUT) request is placed into the tempfile that is connected to the script's standard input. Any output generated on the script's standard output is redirected to a tempfile that is read by the server and transmitted back to the client.


Processing Steps

The cleanest way to start a DOS VM is to use a Windows Program Information File (PIF). The PIF contains a variety of specifications that will be applied to the created DOS VM.

The command interpreter

Normally, the DOS program that is initially exec'ed in the VM is a command interpreter such as COMMAND.COM. This command interpreter is quite limited when compared to some 3rd party alternatives. Keep this in mind.

NOTE:
The output of COMMAND.COM itself cannot be redirected, nor can the output of any script (BAT file) invocation. This creates a nearly intolerable situation where the output of all of the commands in a script must be individually redirected explicitly to the file named in the OUTPUT_FILE environment variable, using the ">" operator for the very first output, and the ">>" operator thereafter. The scripts used for the examples in the httpd online documentation are written this way. Once you look at them, you'll want to get a more useful shell.
An obscure feature of PIF files is that they permit DOS environment variable substitution for the EXE path, the working directory and the optional parameters. Any environment variables used for this purpose must be defined in the "system VM", in other words, before Windows is started. For example, you can use %COMSPEC% for the EXE file and %TEMP% for the working directory. Note that using an environment variable in the EXE file field of the PIF Editor will cause an error alert to appear when you try to save the PIF file. This is an annoyance; the file will be saved as you specified.

Starting the VM

To start the DOS VM, the httpd server execs the following command line:
hscript.pif /c hscript.bat < hscript.inp > hscript.out
hscript.pif is the PIF that actually starts the DOS VM and the command interpreter. Within the PIF file that is shipped with httpd, the EXE file is %COMSPEC%, which starts your DOS command interpreter. The PIF working directory is set to %TEMP% which should be the path to your temporary directory. These must be set properly before starting windows.

The /c is the command interpreter's "exec option", which tells the interpreter to exit when the process finishes (instead of returning to the interactive prompt). This changes to /k if you enable script debugging, so you can see what happened in the DOS VM before it exits.

hscript.bat is the environment initialization "jacket procedure" (see below) that sets the CGI environment variables in the VM environment, then execs the client's target script.

hscript.inp contains any PUT/POST content that came along with the client's request (if any), and hscript.out will receive any output that the script places on its standard output (the redirections are useless to COMMAND.COM).

Environment Initialization

Once the DOS VM has been started, and the command interpreter is running, it is necessary to define the CGI environment variables within the VM's environment. To accomplish this, the server generates a "jacket procedure" that first defines the environment variables and then execs the actual script that is the target of the client request. It looks like this:

  @ECHO OFF
  SET SERVER_SOFTWARE=<whatever>
  ... <other SET statements>
  c:/httpd/cgi-bin/myscript.bat myargs
The @ECHO OFF is required to prevent the environment variable initialization statements from appearing in the script output.

Target script execution

The last line in the jacket procedure invokes the client-specified script for execution in the newly created environment. Any query arguments that appear following a "?" in the URL are put on the script command line.

Post-Processing

When the target script completes, the jacket procedure exits as well. At this point, the server must transmit the results in the output file back to the client. There are two variations on this: Once the result has been transmitted to the client, the server will delete the temporary files.

A Note From the Author

If you read this far, thank you. This is complex stuff.

It's easy to say that Windows is a mess. In my opinion it's an example of the "struggle stage" of a new way of doing things. You can expect things to get more complicted because you can do more things. I love Unix for what it is and what it has done for us all. But those "kinder, gentler" days are passing away. Multi-environment, multi-threaded, GUI/network based systems are here. And it can be complex. So take a deep breath and give this stuff a try.

Once you reach Wizard level, you can try execing other programs (such as a tcl or perl interpreter) directly. There are ways to control the content of the environment initialization "jacket procedure" that the server generates so that the environment variables carrying the client request information can be defined with the appropriate syntax. You can even control the syntax of the command line that is fed to the PIF file. Don't try this at home.

Basic Scripting
Return to the Scripting Overview


Robert B. Denny <rdenny@netcom.com>